package com.gitee.wsl.mathematics.geometry.d3.vertex

import com.gitee.wsl.api.Id
import com.gitee.wsl.mathematics.geometry.d3.edge.toEdgeKindOrNull
import com.gitee.wsl.mathematics.geometry.d3.face.toFaceKindOrNull
import kotlinx.serialization.Serializable
import kotlin.jvm.JvmInline

interface MutableKind<K : Id> {
    var kind: K
}

interface AnyKind

fun String.toAnyKindOrNull(): AnyKind? {
    toEdgeKindOrNull()?.let { return it }
    toVertexKindOrNull()?.let { return it }
    toFaceKindOrNull()?.let { return it }
    return null
}

@Serializable
@JvmInline
value class VertexKind(override val id: Int) : Id, AnyKind, Comparable<VertexKind> {
    override fun compareTo(other: VertexKind): Int = id.compareTo(other.id)
    override fun toString(): String = idString(id, 'A', 'Z')
}

fun String.toVertexKindOrNull() =
    toIdOrNull('A', 'Z')?.let { VertexKind(it) }

internal fun idString(id: Int, from: Char, to: Char): String {
    val n = to - from + 1
    val ch = from + (id % n)
    val rem = id / n
    if (rem == 0) return ch.toString()
    return idString(rem - 1, from, to) + ch
}

internal fun String.toIdOrNull(from: Char, to: Char): Int? {
    return when(length) {
        0 -> null
        1 -> if (first() in from..to) first() - from else null
        else -> {
            val ch = last()
            if (ch !in from..to) return null
            val prefix = dropLast(1).toIdOrNull(from, to) ?: return null
            (prefix + 1) * (to - from + 1) + (ch - from)
        }
    }
}

